package gee

import (
	"log"
	"net/http"
	"strings"
	"time"
)

type Engine struct {
	*RouterGroup
	router *router
	groups []*RouterGroup // store all groups
}

type HandlerFunc func(*Context)

func (e *Engine) Get(pattern string, handler HandlerFunc) {

	e.router.addRoute("GET", pattern, handler)

}
func (e *Engine) POST(pattern string, handler HandlerFunc) {
	e.router.addRoute("POST", pattern, handler)

}
func (e *Engine) PUT(pattern string, handler HandlerFunc) {
	e.router.addRoute("PUT", pattern, handler)

}
func (e *Engine) DELETE(pattern string, handler HandlerFunc) {
	e.router.addRoute("DELETE", pattern, handler)

}
func (e *Engine) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
	var middlewares []HandlerFunc
	for _, group := range e.groups {
		if strings.HasPrefix(request.URL.Path, group.prefix) {
			middlewares = append(middlewares, group.middlewares...)
		}
	}
	c := newContext(writer, request)
	c.handlers = middlewares
	e.router.handle(c)

}

func (e *Engine) Run(addr string) {
	http.ListenAndServe(addr, e)
}
func NewEngine() *Engine {
	engine := &Engine{router: newRouter()}
	engine.RouterGroup = &RouterGroup{engine: engine}
	engine.groups = []*RouterGroup{engine.RouterGroup}
	return engine
}

type RouterGroup struct {
	prefix      string
	middlewares []HandlerFunc
	parents     *RouterGroup
	engine      *Engine
}

func (g *RouterGroup) Group(prefix string) *RouterGroup {

	engine := g.engine
	newGroup := &RouterGroup{
		prefix:  prefix,
		parents: g,
		engine:  engine,
	}
	engine.groups = append(engine.groups, newGroup)
	return newGroup
}
func (g *RouterGroup) addRoute(method string, comp string, handler HandlerFunc) {
	pattern := g.prefix + comp
	log.Printf("Route %4s - %s", method, pattern)
	g.engine.router.addRoute(method, pattern, handler)
}

func (g *RouterGroup) Get(comp string, handler HandlerFunc) {
	g.addRoute("GET", comp, handler)
}

func (g *RouterGroup) POST(pattern string, handler HandlerFunc) {
	g.addRoute("POST", pattern, handler)
}

func (g *RouterGroup) Use(middlewares ...HandlerFunc) {
	g.middlewares = append(g.middlewares, middlewares...)

}
func Logger() HandlerFunc {
	return func(c *Context) {
		// Start timer
		t := time.Now()
		// Process request
		c.Next()
		// Calculate resolution time
		log.Printf("[%d] %s in %v", c.Code, c.Req.RequestURI, time.Since(t))
	}
}
